﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;

namespace Clarendon.AzureBilling.Library
{
    /// <summary>
    /// Class used to get the service properties of an individual service when requested
    /// </summary>
    public class DeploymentsRequester : RequestAzureService
    {
        /// <summary>
        /// An event which the client will subscribe to to return the hosted service list from the Azure subscription
        /// </summary>
        public event AzureHostedServiceEventHandler AzureHostedServiceListReturned;
        /// <summary>
        /// Keeps a count of the updates to the collection class
        /// </summary>
        private int _count = 0;
        /// <summary>
        /// Default constructor for the ServicePropertiesRequester class
        /// </summary>
        public DeploymentsRequester(ServiceManager manager) : base(manager)
        {
            Parser = new XmlParseDeployments();
        }

        /// <summary>
        /// Populate used to parse the XML return from Azure
        /// </summary>
        public override void Populate(HttpWebResponse response)
        {
            using (StreamReader reader = new StreamReader(response.GetResponseStream()))
            {
                lock (this)
                {
                    List<Deployment> deployments = Parser.ParseXmlString<List<Deployment>>(reader.ReadToEnd());
                    // update the item in the collection with an alternative that contains the service properties
                    // TODO: Even though this works order dependence is a terrible way to do this 
                    Trace.WriteLine(String.Format("Azure returned {0} deployments for subscription id {1}", deployments.Count, Manager.SubscriptionId));
                    Manager.HostedServices[_count].Deployments = deployments;

                    // release the semaphore and fire the event to let clients know that the services have been populated
                    if (++_count >= Manager.HostedServices.Count && Manager.Semaphore != null)
                    {
                        ReleaseSemaphore();
                        if(AzureHostedServiceListReturned != null)
                            AzureHostedServiceListReturned(new AzureResponseEventArgs(Manager.HostedServices));
                        Trace.WriteLine(String.Format("Finished getting deployment information for subscription id {0}", Manager.SubscriptionId));

                    }
                }
            }
        }

        /// <summary>
        /// Gets the properties of each service that is hosted in the subscription
        /// </summary>
        public override void MakeServiceRequest()
        {
            var services = Manager.HostedServices;
            // we want to throw an exception if the hosted services list has not been downloaded yet
            if (services == null || services.Count == 0 || services[0].Deployments == null)
                throw new AzureServicesException(
                    "unable to get service information - use the ServiceRequester and ServicePropertiesRequester before DeploymentRequester");
            // iterate through the services to fire off the async requests
            foreach (var service in services)
            {
                // check whether there are any deployments in the collection or if it is null
                if (service.Deployments == null)
                    continue;
                // iterate through the deployments and get each deployment and then get details about the role instances
                foreach (var deployment in service.Deployments)
                {
                    ServiceManagementRequest serviceManager = GetServiceManagementRequest(String.Format("hostedservices/{0}/deployments/{1}", service.Name, deployment.Name));
                    QueryManager.MakeASyncRequest(serviceManager, Manager.CertificateFile,
                        new ServiceManager.AsyncResponseParser(Populate));
                    //Interlocked.Increment(ref _count);    
                }
                
            }
        }
    }
}
